package com.ml.service.impl;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ml.service.DatasService;
import com.ml.ws.model.DepthResp;
import com.ml.ws.model.PeriodLastKline;
import com.ml.ws.model.TickerResp;
import com.virgil.redis.util.RedisUtil;

@Service
public class DatasServiceImpl implements DatasService {
	@Autowired
	RedisUtil redisUtil;

	@Override
	public void genKline(String period) {
		List<String> symbols = getSymbols();

		for (String symbol : symbols) {
			String periodLastKLine_key = symbol + ":periodLastKline:" + period;
			String klineData_key = symbol + ":klineData:back:" + period;
			String lastKlineString = redisUtil.get(periodLastKLine_key);
			// 初始化
			PeriodLastKline kline = initPeriodLastKline(symbol, period);
			PeriodLastKline oldKline = null;
			if (StringUtils.isNotEmpty(lastKlineString)) {
				oldKline = JSON.parseObject(lastKlineString, PeriodLastKline.class);
				kline.setHigh(oldKline.getLast());
				kline.setLow(oldKline.getLast());
				kline.setOpen(oldKline.getLast());
				kline.setLast(oldKline.getLast());
			} else {
				oldKline = initPeriodLastKline(symbol, period);
				oldKline.setStartTime(oldKline.getStartTime() + 60);
			}
			// 更新periodLastKLine
			redisUtil.set(periodLastKLine_key, JSON.toJSONString(kline));
			// 缓存K线历史数据
			redisUtil.zadd(klineData_key, oldKline.getStartTime().doubleValue(), JSON.toJSONString(oldKline));

		}
	}

	@Override
	public PeriodLastKline lastKline(String symbol, String period) {

		String lastKlineString = redisUtil.get(symbol + ":periodLastKline:" + period);
		String currentExchangPriceString = redisUtil.get(symbol + ":currentExchangPrice");

		PeriodLastKline lastKline = null;
		if (StringUtils.isNotEmpty(lastKlineString)) {
			lastKline = JSON.parseObject(lastKlineString, PeriodLastKline.class);
			if (StringUtils.isNotEmpty(currentExchangPriceString)) {
				lastKline.setLast(new BigDecimal(currentExchangPriceString));
			}
		} else {
			lastKline = initPeriodLastKline(symbol, period);
		}
		return lastKline;
	}

	@Override
	public List<String> getSymbols() {
		String symbolString = redisUtil.get("sys:symbolList");
		List<String> symbols = null;
		if (StringUtils.isNotEmpty(symbolString)) {
			symbols = JSONArray.parseArray(symbolString, String.class);
		}
		return symbols;
	}

	@Override
	public DepthResp getDepth(String symbol, Integer size) {
		// TODO
		// 买盘
		Set<String> buySet = redisUtil.zrevrangeByScore(symbol + "_buy", Double.MAX_VALUE, 0);
		Iterator<String> buyIterator = buySet.iterator();

		// 卖盘
		Set<String> sellSet = redisUtil.zrangeByScore(symbol + "_sell", Double.MAX_VALUE, 0);
		Iterator<String> sellIterator = sellSet.iterator();
		return null;
	}
	
	@Override
	public Map<String, TickerResp> getTicker() {
		// TODO Auto-generated method stub
		return null;
	}

	public PeriodLastKline initPeriodLastKline(String symbol, String period) {
		PeriodLastKline periodLastKline = new PeriodLastKline();
		String currentExchangPrice_key = symbol + ":currentExchangPrice";
		String currentExchangPriceString = redisUtil.get(currentExchangPrice_key);
		BigDecimal currentExchang = BigDecimal.ZERO;
		if (StringUtils.isNoneEmpty(currentExchangPriceString)) {
			currentExchang = new BigDecimal(currentExchangPriceString);
		}
		periodLastKline.setOpen(currentExchang);
		periodLastKline.setHigh(currentExchang);
		periodLastKline.setLast(currentExchang);
		periodLastKline.setLow(currentExchang);
		periodLastKline.setPeriod(period);
		periodLastKline.setSymbol(symbol);
		periodLastKline.setVol(BigDecimal.ZERO);

		Long[] time = fromToTime(period);
		periodLastKline.setStartTime(time[0]);
		periodLastKline.setEndTime(time[1]);

		return periodLastKline;
	}

	/**
	 * 计算当前时间K线的对应周期范围的起始时间
	 */
	public Long[] fromToTime(String period) {
		Long start = 0L, end = 0L;
		// 获取前月的第一天
		Calendar startCal = Calendar.getInstance();
		Calendar endCal = Calendar.getInstance();
		switch (period) {
		case "1":
			startCal.set(Calendar.SECOND, 0);
			start = startCal.getTimeInMillis() / 1000;
			end = start + 60;
			break;
		case "5":
			startCal.set(Calendar.SECOND, 0);
			startCal.set(Calendar.MINUTE, startCal.get(Calendar.MINUTE) / 5 * 5);
			start = startCal.getTimeInMillis() / 1000;
			end = start + 300;
			break;
		case "15":
			startCal.set(Calendar.SECOND, 0);
			startCal.set(Calendar.MINUTE, startCal.get(Calendar.MINUTE) / 15 * 15);
			start = startCal.getTimeInMillis() / 1000;
			end = start + 900;
			break;
		case "30":
			startCal.set(Calendar.SECOND, 0);
			startCal.set(Calendar.MINUTE, startCal.get(Calendar.MINUTE) / 30 * 30);
			start = startCal.getTimeInMillis() / 1000;
			end = start + 1800;
			break;
		case "60":
			startCal.set(Calendar.MINUTE, 0);
			startCal.set(Calendar.SECOND, 0);
			start = startCal.getTimeInMillis() / 1000;
			end = start + 3600;
			break;
		case "240":
			startCal.set(Calendar.MINUTE, 0);
			startCal.set(Calendar.SECOND, 0);
			startCal.set(Calendar.HOUR, startCal.get(Calendar.HOUR_OF_DAY) / 4 * 4);
			start = startCal.getTimeInMillis() / 1000;
			end = start + 14400;
			break;
		case "1440":
			startCal.set(Calendar.MINUTE, 0);
			startCal.set(Calendar.SECOND, 0);
			startCal.set(Calendar.HOUR, 0);
			start = startCal.getTimeInMillis() / 1000;
			end = start + 86400;
			break;
		case "10080":
			startCal.set(Calendar.MINUTE, 0);
			startCal.set(Calendar.SECOND, 0);
			startCal.set(Calendar.HOUR, 0);
			startCal.set(Calendar.DAY_OF_WEEK, 1);
			start = startCal.getTimeInMillis() / 1000 + 86400;
			end = start + 604800;
			break;
		case "43200":
			startCal.set(Calendar.MINUTE, 0);
			startCal.set(Calendar.SECOND, 0);
			startCal.set(Calendar.HOUR, 0);
			startCal.set(Calendar.DAY_OF_MONTH, 1);
			start = startCal.getTimeInMillis() / 1000;
			endCal.set(Calendar.MINUTE, 0);
			endCal.set(Calendar.SECOND, 0);
			endCal.set(Calendar.HOUR, 0);
			endCal.set(Calendar.DAY_OF_MONTH, endCal.getActualMaximum(Calendar.DAY_OF_MONTH));
			end = endCal.getTimeInMillis() / 1000;
			break;
		default:
			start = 0L;
			end = 0L;
			break;
		}
		Long time[] = new Long[2];
		time[0] = start;
		time[1] = end;
		return time;
	}



}
